package com.wooming.myserver.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 随机触发工具类
 *
 * @author wooming 2025/05/22
 */
public class PercentRandom {

    /**
     * 真随机1
     *
     * @param percent 百分比
     * @return 是否触发
     */
    public static boolean trueRandom(double percent) {
        return Math.random() < percent / 100;
    }

    /**
     * 真随机2
     *
     * @param max 分母
     * @param p   分子
     * @return 是否触发
     */
    public static boolean trueRandom(int p, int max) {
        return Math.random() * max < p;
    }



    // 以下内容为PRD伪随机触发实现逻辑,如后续需优化再修改,此部分暂时不使用

    // 记忆缓存：存储不同暴击率对应的C值（预计算优化）
    private static final Map<Double, Double> cCache = new ConcurrentHashMap<>();

    // 根据目标暴击率P计算C值（二分法）
    private static double calculateC(double targetP) {
        double low = 0, high = 1, epsilon = 1e-9;
        for (int i = 0; i < 100; i++) {
            double mid = (low + high) / 2;
            double estimatedP = estimatePFromC(mid);
            if (Math.abs(estimatedP - targetP) < epsilon) return mid;
            if (estimatedP > targetP) high = mid;
            else low = mid;
        }
        return (low + high) / 2;
    }

    // 通过C值估算实际暴击率
    private static double estimatePFromC(double c) {
        double survivalProb = 1, ePN = 0;
        for (int k = 1; k <= 1e6; k++) {
            double currentProb = survivalProb * Math.min(1, k * c);
            ePN += k * currentProb;
            survivalProb *= (1 - Math.min(1, k * c));
            if (survivalProb < 1e-12) break;
        }
        return 1 / ePN;
    }

    // 封装攻击状态
    private static class PRDState {
        int currentN = 1;
        double c;
    }

    // 记忆存储：Key为暴击率百分比，Value为对应的状态
    private static final Map<Double, PRDState> stateCache = new ConcurrentHashMap<>();

    public static boolean checkCriticalHit(double percentage) {
        double p = percentage / 100.0; // 转换为0-1概率
        PRDState state = stateCache.computeIfAbsent(percentage, k -> {
            PRDState s = new PRDState();
            s.c = cCache.computeIfAbsent(p, PercentRandom::calculateC);
            return s;
        });

        // 计算本次暴击率
        double currentProb = Math.min(1, state.currentN * state.c);
        boolean isCritical = Math.random() < currentProb;

        // 更新记忆状态
        state.currentN = isCritical ? 1 : state.currentN + 1;
        return isCritical;
    }
}
